#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
#include <sys/time.h>
#include <stdlib.h>
#include <cmath>
using namespace std;

int main(int argc, char ** argv){
	float max = 1.0;
	float min = -1.0;
	int liczbaGeneratorow;
	int liczbaPrzedzialow;
	struct timeval ti;
	ifstream dane("dane.dat");
	string line;
	int i = 0;
	vector< vector<double> > generatory;
	vector< vector<double> > przedzialy;
	
	
//-------------------------------------------------------------------------------------------------------------------------------------------------------
//CZYTANIE PLIKU: LICZBA GENERATOROW

	while (getline(dane,line)){
		if (i == 0) {
			istringstream iss(line);
			iss >> liczbaGeneratorow;
		}
		i++;
	}

//-------------------------------------------------------------------------------------------------------------------------------------------------------
//CZYTANIE PLIKU: DANE GENERATOROW

	i = 0;
	dane.clear();
	dane.seekg(0, ios::beg);
	while (getline(dane,line)) {
		if (i == 0) {
			i++;
		} else if (i < liczbaGeneratorow+1) {
			istringstream iss(line);
			vector<double> temp;
			for(int j = 0; j < 3; j++){
				double k;
				iss >> k;
				temp.push_back(k);
			}
			generatory.push_back(temp);
			i++;
		} else if (i == liczbaGeneratorow + 1) {
			istringstream iss(line);
			iss >> liczbaPrzedzialow;
			i++;
		}
	}

//-------------------------------------------------------------------------------------------------------------------------------------------------------
//CZYTANIE PLIKU: DANE PRZEDZIALOW

	i = 0;
	dane.clear();
	dane.seekg(0, ios::beg);
	while (getline(dane,line)) {
		if (i < liczbaGeneratorow + 2) {
			i++;
		} else if (i >= liczbaGeneratorow + 2) {
			istringstream iss(line);
			double k;
			vector<double> temp;
			for (int j = 0; j < 2; j++) {
				iss >> k;
				temp.push_back(k);
			}
			temp.push_back(0);
			przedzialy.push_back(temp);
		}
	}
	
//-------------------------------------------------------------------------------------------------------------------------------------------------------
//TEST WCZYTYWANIA
/*
	cout << "Liczba generatorow: " << liczbaGeneratorow << ", generatory: " << endl;
	for (int j = 0; j < liczbaGeneratorow; j++) {
		cout << "Generator nr "<< j << ", srednia: " << generatory[j][0] << ", wariancja: " << generatory[j][1] << ", ile liczb: " << generatory[j][2] << endl;
	}
	cout << "Liczba przedzialow: " << liczbaPrzedzialow << ", przedzialy: " << endl;
	for (int j = 0; j < liczbaPrzedzialow; j++) {
		cout << "Przedzial nr "<< j << ", poczatek: " << przedzialy[j][0] << ", koniec: " << przedzialy[j][1] << ", trafien: " << przedzialy[j][2] << endl;
	}
*/	
//-------------------------------------------------------------------------------------------------------------------------------------------------------
//GLOWNE PETLE
	struct drand48_data drand_buffer;
	srand48_r(time(NULL), &drand_buffer);
	double x = 0;
	double y = 0;
	
	for (int g = 0; g < liczbaGeneratorow; g++) {
	#pragma omp parallel shared(przedzialy) private(x,y)
	{
		#pragma omp for
		for (int m = 0; m < (int)generatory[g][2]; m++) {
			float omega = 0;
			do {
			drand48_r(&drand_buffer, &x);
			x = x * 2.0 - 1.0;
			drand48_r(&drand_buffer, &y);
			y = y * 2.0 - 1.0;
			omega = pow(x,2) + pow(y,2);
			} while (omega < 0 || omega > 1);
			double number = generatory[g][0] + x * sqrt(generatory[g][1]) * sqrt(-2.0*log(omega)/omega);
			for (int n = 0; n < liczbaPrzedzialow; n++) {
				if (number > przedzialy[n][0] && number < przedzialy[n][1]){
					#pragma omp critical
					{
						przedzialy[n][2] += 1;
					}
				}
			}
		}
	}
	}

//-------------------------------------------------------------------------------------------------------------------------------------------------------
//OUTPUT

	for (int n = 0; n < liczbaPrzedzialow; n++) {
		cout << n << " " << przedzialy[n][0] << " " << przedzialy[n][1] << " " << (long)przedzialy[n][2] << endl;
	}
}
